import { _decorator, Collider, color, Component, instantiate, macro, math, MeshRenderer, Node, Prefab, Vec3 } from 'cc';
import { Bullet } from './Bullet';
import { Constand } from './Constant';
import { EnemyPlane } from './EnemyPlane';
import { Item } from './Item';
import { UiManager } from './UiManager';
import { AuidoManager } from './AuidoManager';
import { PoolMananger } from './PoolMananger';
import { SelPlane } from './SelPlane';
const { ccclass, property, requireComponent, menu } = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {
    private static instance: GameManager = null;
    @property(Node)
    public playerPlane: Node = null;
    @property(Prefab)
    public bullet01: Prefab = null;
    @property(Prefab)
    public bullet02: Prefab = null;
    @property(Prefab)
    public bullet03: Prefab = null;
    @property(Prefab)
    public bullet04: Prefab = null;
    @property(Prefab)
    public bullet05: Prefab = null;

    @property
    public bulletSpeed = 1;
    @property
    public shootTime = 0.3;
    @property(Node)
    public bulletRoot: Node = null;

    @property(Prefab)
    public enemy01: Prefab = null;
    @property(Prefab)
    public enemy02: Prefab = null;

    @property(Prefab)
    public itemM: Prefab = null;
    @property(Prefab)
    public itemH: Prefab = null;
    @property(Prefab)
    public itemS: Prefab = null;
    @property
    public itemSpeed = 0.3;

    //敌机生成时间
    @property
    public createEnemyTime = 1;
    //玩家移动速度
    @property
    public speed = 80;

    //爆炸特效(大)
    @property(Prefab)
    public explodeBig: Prefab = null;
    //爆炸特效(小)
    @property(Prefab)
    public explodeSamll: Prefab = null;

    //敌机速度
    public enemy1Speed = 10;
    public enemy2Speed = 13;
    //游戏状态
    public status = Constand.GameStatus.START;
    //玩家最大血量
    public hpMax = 100;
    //玩家当前血量
    public hpCurr = 100;

    //当前分数
    public score = 0;

    private _currSHootTime = 0;
    private _isTouching = false;
    private _currCreateEnemyTime = 0;
    private _combinationInterval = Constand.Combination.PLAN1;
    private _bulletType = Constand.BulletType.M;

    public static getInstance(): GameManager {
        return GameManager.instance;
    }
    onLoad() {
        GameManager.instance = this;
    }

    startGame(){
        this.status = Constand.GameStatus.GAME;
        this._currSHootTime = this.shootTime;
        this.createItem();
        this.schedule(this._onSchedule, 10, macro.REPEAT_FOREVER);
        this.hpCurr = this.hpMax;
        UiManager.getInstance().updateHp();
    }

    private _onSchedule(){
        this._combinationInterval++;
        this.createItem();
    }

    gameOver(){
        this.unschedule(this._onSchedule)
        this.status = Constand.GameStatus.OVER;
        this.playerPlane.active = false;
        UiManager.getInstance().over();
    }

    reStart(){
        this.reSet();
        this.startGame();
    }

    reSet(){
        //重置所有数据
        this.playerPlane.setPosition(0, 0, 30);
        this.playerPlane.active = true;
        this.hpCurr = this.hpMax;
        UiManager.getInstance().updateHp();
        //清除所有敌机
        let enemys = this.node.children;
        for(let i = enemys.length - 1; i >= 0; i--){
            PoolMananger.getInstance().putNode(enemys[i]);
        }
        //清除所有子弹
        let bullets = this.bulletRoot.children;
        for(let i = bullets.length - 1; i >= 0; i--){
            PoolMananger.getInstance().putNode(bullets[i]);
        }
        //重置子弹
        this._bulletType = Constand.BulletType.M;
        //重置刷怪波次
        this._currSHootTime = 0;
        this._isTouching = false;
        this._currCreateEnemyTime = 0;
        this._combinationInterval = Constand.Combination.PLAN1;
        this.status = Constand.GameStatus.START;
        //重置分数
        this.score = 0;
        UiManager.getInstance().updateScore();
    }

    createItem() {
        //随机道具id
        let randmoBullet = math.randomRangeInt(1, 4);
        let prefab: Prefab = null;
        if (randmoBullet == 1) {
            prefab = this.itemM;
        } else if (randmoBullet == 2) {
            prefab = this.itemH;
        } else if (randmoBullet == 3) {
            prefab = this.itemS;
        } else {
            prefab = this.itemM;
        }
        const item = PoolMananger.getInstance().getNode(prefab,this.node);
        item.setPosition(15, 0, -60);
        const itemComp = item.getComponent(Item);
        itemComp.setSpeed(-this.itemSpeed);
    }

    update(deltaTime: number) {
        if(this.status != Constand.GameStatus.GAME){
            return;
        }
        this._currSHootTime += deltaTime;
        if (this._isTouching && this._currSHootTime > this.shootTime) {
            switch (this._bulletType) {
                case Constand.BulletType.M:
                    this.createPlayerBulletM();
                    break;
                case Constand.BulletType.H:
                    this.createPlayerBulletH();
                    break;
                case Constand.BulletType.S:
                    this.createPlayerBulletS();
                    break;
            }
            this._currSHootTime = 0;
        }
        this._currCreateEnemyTime += deltaTime;
        if (this._combinationInterval == Constand.Combination.PLAN1) {
            if (this._currCreateEnemyTime > this.createEnemyTime) {
                this.createEnemyPlane();
                this._currCreateEnemyTime = 0;
            }
        } else if (this._combinationInterval == Constand.Combination.PLAN2) {
            if (this._currCreateEnemyTime > this.createEnemyTime * 0.9) {
                const randomCombo = math.randomRangeInt(1, 3);
                if (randomCombo == Constand.Combination.PLAN2) {
                    this.createCombination1();
                } else {
                    this.createEnemyPlane();
                }
                this._currCreateEnemyTime = 0;
            }
        } else {
            if (this._currCreateEnemyTime > this.createEnemyTime * 0.8) {
                const randomCombo = math.randomRangeInt(1, 4);
                if (randomCombo == Constand.Combination.PLAN3) {
                    this.createCombination2();
                } else if (randomCombo == Constand.Combination.PLAN2) {
                    this.createCombination1();
                } else {
                    this.createEnemyPlane();
                }
                this._currCreateEnemyTime = 0;
            }
        }
    }

    createEnemyBullet(targetPos: Vec3, type: number) {
        let prefab: Prefab = null;
        if(type == 1){
            prefab = this.bullet02;
        }else{
            prefab = this.bullet04;
        }
        const bullet = PoolMananger.getInstance().getNode(prefab,this.bulletRoot);
        bullet.setPosition(targetPos.x, targetPos.y, targetPos.z + 4);
        const bulleComp = bullet.getComponent(Bullet);
        bulleComp.setSpeed(1, true);
        const collider = bullet.getComponent(Collider);
        collider.setGroup(Constand.CollistionType.E_BULLET);
        collider.setMask(Constand.CollistionType.PLAYER)
    }

    public createCombination1() {
        const enemyArray = new Array<Node>(5);
        for (let i = 0; i < enemyArray.length; i++) {
            enemyArray[i] = PoolMananger.getInstance().getNode(this.enemy01,this.node);
            const element = enemyArray[i];
            element.setPosition(-20 + i * 10, 0, -60);
            const enemyComp = element.getComponent(EnemyPlane);
            enemyComp.setSpeed(this.enemy1Speed, false);
        }
    }

    public createCombination2() {
        const enemyArray = new Array<Node>(7);
        const CombinationPos = [
            -21, 0, -60,
            -14, 0, -55,
            -7, 0, -50,
            0, 0, -45,
            7, 0, -50,
            14, 0, -55,
            21, 0, -60,
        ]
        for (let i = 0; i < enemyArray.length; i++) {
            enemyArray[i] = PoolMananger.getInstance().getNode(this.enemy02,this.bulletRoot);
            const element = enemyArray[i];
            let starIndex = i * 3;
            element.setPosition(CombinationPos[starIndex], CombinationPos[starIndex + 1], CombinationPos[starIndex + 2]);
            const enemyComp = element.getComponent(EnemyPlane);
            enemyComp.setSpeed(this.enemy2Speed, false);
        }
    }

    public createEnemyPlane() {
        const random = math.randomRangeInt(1, 3);
        let prefab: Prefab = null;
        let speed = 0;
        if (random == Constand.EnemyType.TYPE1) {
            prefab = this.enemy01;
            speed = this.enemy1Speed;
        } else {
            prefab = this.enemy02;
            speed = this.enemy2Speed;
        }
        let enemy = PoolMananger.getInstance().getNode(prefab,this.node);
        let enemyComp = enemy.getComponent(EnemyPlane);
        enemyComp.setSpeed(speed, true);

        const randomPos = math.randomRangeInt(-21, 21);
        enemy.setPosition(randomPos, 0, -60);
    }

    //发射M弹
    public createPlayerBulletM() {
        const bullet = PoolMananger.getInstance().getNode(this.bullet01,this.bulletRoot);
        const pos = this.playerPlane.position;
        bullet.setPosition(pos.x, pos.y, pos.z - 5);
        const bulleComp = bullet.getComponent(Bullet);
        bulleComp.setSpeed(this.bulletSpeed, false);
        AuidoManager.getInstance().play("bullet1");
    }

    //发射H弹
    public createPlayerBulletH() {
        const pos = this.playerPlane.position;

        const bullet = PoolMananger.getInstance().getNode(this.bullet03,this.bulletRoot);
        bullet.setPosition(pos.x - 2.5, pos.y, pos.z - 5);
        const bulleComp = bullet.getComponent(Bullet);
        bulleComp.setSpeed(this.bulletSpeed, false);

        const bullet2 = PoolMananger.getInstance().getNode(this.bullet03,this.bulletRoot);
        bullet2.setPosition(pos.x + 2.5, pos.y, pos.z - 5);
        const bulleComp2 = bullet2.getComponent(Bullet);
        bulleComp2.setSpeed(this.bulletSpeed, false);
        AuidoManager.getInstance().play("bullet1");
    }

    //发射S弹
    public createPlayerBulletS() {
        const pos = this.playerPlane.position;

        const bullet = PoolMananger.getInstance().getNode(this.bullet05,this.bulletRoot);
        bullet.setPosition(pos.x - 4, pos.y, pos.z - 5);
        const bulleComp = bullet.getComponent(Bullet);
        bulleComp.setSpeed(this.bulletSpeed, false, Constand.Direction.LEFT);

        const bullet2 = PoolMananger.getInstance().getNode(this.bullet05,this.bulletRoot);
        bullet2.setPosition(pos.x, pos.y, pos.z - 5);
        const bulleComp2 = bullet2.getComponent(Bullet);
        bulleComp2.setSpeed(this.bulletSpeed, false);

        const bullet3 = PoolMananger.getInstance().getNode(this.bullet05,this.bulletRoot);
        bullet3.setPosition(pos.x + 4, pos.y, pos.z - 5);
        const bulleComp3 = bullet3.getComponent(Bullet);
        bulleComp3.setSpeed(this.bulletSpeed, false, Constand.Direction.RIGHT);
        AuidoManager.getInstance().play("bullet2");
    }

    public isShooting(value: boolean) {
        this._isTouching = value;
    }

    public addScore() {
        this.score ++;
        UiManager.getInstance().updateScore();
    }

    public changeBullet(type: number) {
        this._bulletType = type;
    }

    /**
     * 创建爆炸
     * @param pos 位置 
     * @param type 1:大爆炸 2:小爆炸
     */
    public createExplode(pos: Vec3, type: number){
        let explode = null;
        if(type == 1){
            explode = PoolMananger.getInstance().getNode(this.explodeBig,this.node);
        }else{
            explode = PoolMananger.getInstance().getNode(this.explodeSamll,this.node);
        }
        //将爆炸设置到目标位置
        explode.setPosition(pos.x,pos.y,pos.z);
        //开启定时器，2秒后回收爆炸节点
        this.scheduleOnce(() => {
            PoolMananger.getInstance().putNode(explode);
        }, 2)
    }

}
